<template>
	<div class="compFrameScroll">
		<div
			ref="inb" class="inbox"
			:class="{ verNop: ver_ == 0, verFix: ver_ == 2, horNop: hor_ == 0, horFix: hor_ == 2 }"
			:style="{ width: inbWidth, height: inbHeight }"
			@scroll="barRoll"
		>
			<slot />
		</div>
		<div v-show="barSize > 0 && barVerShow" ref="barVer" class="bar ver" @mousedown="barDownVer" @touchstart="barDownVer" />
		<div v-show="barSize > 0 && barHorShow" ref="barHor" class="bar hor" @mousedown="barDownHor" @touchstart="barDownHor" />
	</div>
</template>

<script>
	export default {
		props: {
			ver: {
				type: [String, Boolean],
				default: 'float'
			},
			hor: {
				type: [String, Boolean],
				default: 'float'
			},
		},

		data() {
			let event = ('ontouchstart' in window) ?
				{
					down: 'touchstart',
					move: 'touchmove',
					up: 'touchend',
					over: 'touchstart',
					out: 'touchend'
				} :
				{
					down: 'mousedown',
					move: 'mousemove',
					up: 'mouseup',
					over: 'mouseover',
					out: 'mouseout'
				};

			return {
				mobile: ('ontouchstart' in window),

				event: event,

				downVer: false,
				downHor: false,

				barVerShow: false,
				barHorShow: false,
			};
		},

		computed: {
			ver_() {
				let ver = this.ver;

				if(ver === true || ver == 'float') {
					return 1;
				}
				else if(ver == 'fixed') {
					return 2;
				}

				return 0;
			},
			hor_() {
				let hor = this.hor;

				if(hor === true || hor == 'float') {
					return 1;
				}
				else if(hor == 'fixed') {
					return 2;
				}

				return 0;
			},
			barSize() {
				const odiv = document.createElement('div');

				odiv.style.width = '100px';
				odiv.style.overflowY = 'scroll';

				document.body.appendChild(odiv);

				const barSize = odiv.offsetWidth - odiv.clientWidth;

				odiv.remove();

				return barSize;
			},
			inbWidth() {
				return this.ver_ == 0 ? false : `calc(100% + ${1 + (this.ver_ == 2 ? -12 : 0)}px + ${this.barSize}px)`;
			},
			inbHeight() {
				return this.hor_ == 0 ? false : `calc(100% + ${1 + (this.hor_ == 2 ? -12 : 0)}px + ${this.barSize}px)`;
			}
		},

		mounted() {
			window.addEventListener('resize', this.onUpdate);

			this.$nextTick(() => this.onUpdate());
		},

		updated() {
			this.$nextTick(() => this.onUpdate());
		},

		destroyed() {
			window.removeEventListener('resize', this.onUpdate);
		},

		methods: {
			barRoll(event) {
				if(this.barSize == 0) {
					return;
				}

				let inb = this.$refs.inb;

				if(inb.scrollHeight > inb.clientHeight) {
					let barVer = this.$refs.barVer;

					barVer.style.top = (inb.scrollTop * inb.clientHeight / inb.scrollHeight) - 1 + 'px';
				}

				if(inb.scrollWidth > inb.clientWidth) {
					let barHor = this.$refs.barHor;

					barHor.style.left = (inb.scrollLeft * inb.clientWidth / inb.scrollWidth) - 1 + 'px';
				}

				this.$emit('scroll', event);
			},
			barDownVer() {
				let barVer = this.$refs.barVer;

				document.addEventListener(this.event.move, this.barMoveVer);
				document.addEventListener(this.event.up, this.barUponVer);

				document.body.className += ' nosel';
				barVer.style.backgroundColor = 'rgba(119, 119, 119, 0.7)';

				this.downVer = true;

				return false;
			},
			barDownHor() {
				let barHor = this.$refs.barHor;

				document.addEventListener(this.event.move, this.barMoveHor);
				document.addEventListener(this.event.up, this.barUponHor);

				document.body.className += ' nosel';
				barHor.style.backgroundColor = 'rgba(119, 119, 119, 0.7)';

				this.downHor = true;

				return false;
			},
			barUponVer() {
				let barVer = this.$refs.barVer;

				this.downVer = false;

				barVer.style.backgroundColor = '';
				document.body.className = document.body.className.replace(/ nosel/g, '');

				document.removeEventListener(this.event.move, this.barMoveVer);
				document.removeEventListener(this.event.up, this.barUponVer);

				return false;
			},
			barUponHor() {
				let barHor = this.$refs.barHor;

				this.downHor = false;

				barHor.style.backgroundColor = '';
				document.body.className = document.body.className.replace(/ nosel/g, '');

				document.removeEventListener(this.event.move, this.barMoveHor);
				document.removeEventListener(this.event.up, this.barUponHor);

				return false;
			},
			barMoveVer(e) {
				if(this.downVer) {
					let inb = this.$refs.inb;
					let barVer = this.$refs.barVer;

					if(inb.scrollHeight > inb.clientHeight) {
						let top = barVer.offsetTop + e.movementY;
						let max = inb.clientHeight - (inb.clientHeight * inb.clientHeight / inb.scrollHeight) - 1;

						if(top >= 0 && top <= max) {
							barVer.style.top = top + 'px';
							inb.scrollTop = (top * inb.scrollHeight / inb.clientHeight);
						}
					}
				}

				return false;
			},
			barMoveHor(e) {
				if(this.downHor) {
					let inb = this.$refs.inb;
					let barHor = this.$refs.barHor;

					if(inb.scrollWidth > inb.clientWidth) {
						let left = barHor.offsetLeft + e.movementX;
						let max = inb.clientWidth - (inb.clientWidth * inb.clientWidth / inb.scrollWidth);

						if(left >= 0 && left <= max) {
							barHor.style.left = left + 'px';
							inb.scrollLeft = (left * inb.scrollWidth / inb.clientWidth);
						}
					}
				}

				return false;
			},

			onUpdate() {
				let inb = this.$refs.inb;
				let barVer = this.$refs.barVer;
				let barHor = this.$refs.barHor;

				setTimeout(() => {
					barVer.style.height = (inb.clientHeight * inb.clientHeight / inb.scrollHeight) + 'px';
					this.barVerShow = this.ver_ && inb.scrollHeight > inb.clientHeight;

					barHor.style.width = (inb.clientWidth * inb.clientWidth / inb.scrollWidth) + 'px';
					this.barHorShow = this.hor_ && inb.scrollWidth > inb.clientWidth;
				}, 41);
			}
		},
	};
</script>

<style scoped>
	.compFrameScroll {
		position: relative;

		overflow: hidden;
	}

	.inbox {
		position: relative;

		overflow: scroll;

		transition-property: none;
	}
	.inbox.verFix {
		padding-right: 12px;
	}
	.inbox.horFix {
		padding-bottom: 12px;
	}
	.inbox.verNop {
		width: 100%;
		overflow-y: hidden;
	}
	.inbox.horNop {
		height: 100%;
		overflow-x: hidden;
	}

	.bar {
		position: absolute;

		cursor: pointer;

		border-radius: 5px;
		background: rgba(145, 145, 145, 0.4);

		transition-property: none;
	}
	.bar.ver {
		width: 10px;

		top: 0px;
		right: 0px;
	}
	.bar.hor {
		height: 10px;

		bottom: 0px;
		left: 0px;
	}
	.bar:hover {
		background: rgba(145, 145, 145, 0.7);
	}
</style>